﻿/**************************************************************
 *
 * 唯一标识：6322bbe9-28e8-44b9-84d6-b9bde1603171
 * 命名空间：Sgr.UPMS.Application.Commands.Organizations
 * 创建时间：2023/8/24 17:26:18
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：组织机构注销命令处理器
 *
 **************************************************************/

using MediatR;
using Sgr.Application.Commands;
using Sgr.Security.Tokens.Services;
using Sgr.UPMS.Domain.Organizations;
using Sgr.UPMS.Domain.Users;
using System.Threading;
using System.Threading.Tasks;

namespace Sgr.UPMS.Application.Commands.Organizations
{
    /// <summary>
    /// 组织机构注销命令处理器
    /// </summary>
    public class CancellationOrgCommandHandle : IRequestHandler<CancellationOrgCommand, CommandResult<bool>>
    {
        /// <summary>
        /// 组织注销二次密码验证令牌类型索引
        /// </summary>
        public const int CancellationOrgTokenTypeIndex = 1002;

        private readonly IOrganizationManage _organizationManage;
        private readonly IOrganizationRepository _organizationRepository;
        private readonly IUserRepository _userRepository;
        private readonly ITemporaryTokenService _temporaryTokenService;
        private readonly ICurrentUser _currentUser;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="organizationManage">组织机构管理器</param>
        /// <param name="organizationRepository">组织机构仓储</param>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="temporaryTokenService">临时令牌服务</param>
        /// <param name="currentUser">当前用户</param>
        public CancellationOrgCommandHandle(IOrganizationManage organizationManage,
            IOrganizationRepository organizationRepository,
            IUserRepository userRepository,
            ITemporaryTokenService temporaryTokenService,
            ICurrentUser currentUser)
        {
            _organizationManage = organizationManage;
            _organizationRepository = organizationRepository;
            _userRepository = userRepository;
            _temporaryTokenService = temporaryTokenService;
            _currentUser = currentUser;
        }

        /// <summary>
        /// 处理组织机构注销命令
        /// </summary>
        /// <param name="request">命令请求</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处理结果</returns>
        public async Task<CommandResult<bool>> Handle(CancellationOrgCommand request, CancellationToken cancellationToken)
        {
            // 二次密码验证
            bool tokenIsValid = await _temporaryTokenService.ValidateAsync(
                code: request.TemporaryToken,
                tokenType: CancellationOrgTokenTypeIndex,
                content: null,
                deviceFingerprint: _currentUser.DeviceFingerprint,
                userId: _currentUser.Id,
                cancellationToken: cancellationToken);

            if (!tokenIsValid)
                return CommandResult.Invalid<bool>("二次密码验证失败，请重新输入密码");

            // 查找组织机构
            var org = await _organizationRepository.GetAsync(request.Id, cancellationToken);
            if (org == null)
                return CommandResult.NotFound<bool>("未找到指定的组织机构");

            // 组织注销前审查
            var userValidationResult = await ValidateRules(org, cancellationToken);
            if (!userValidationResult)
                return CommandResult.Unauthorized<bool>($"您没有权限注销组织机构 [{org.Name}]，可能是因为您不是组织管理员或该组织存在下级组织");

            // 执行注销 - 通过领域模型方法
            org.Cancellation();

            // 更新状态
            await _organizationRepository.UpdateAsync(org, cancellationToken);

            // 返回成功结果
            return CommandResult.Success(true, "组织注销成功");
        }

        /// <summary>
        /// 验证用户是否有权限注销组织
        /// </summary>
        /// <param name="organization">组织机构</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>验证结果，true表示验证通过，false表示验证失败</returns>
        private async Task<bool> ValidateRules(Organization organization, CancellationToken cancellationToken)
        {
            // 验证当前用户ID是否有效
            if (!long.TryParse(_currentUser.Id, out long userId))
                return false;

            // 获取当前用户
            var user = await _userRepository.GetAsync(userId, cancellationToken);
            if (user == null)
                return false;

            // 调用领域服务进行注销审查
            // 1. 仅能由当前组织的系统管理员才能执行注销操作
            // 2. 如果当前组织有下级组织，不允许注销
            var result = await _organizationManage.CancellationExamination(organization, user, cancellationToken);
            return result.IsComply;
        }
    }
}